home *** CD-ROM | disk | FTP | other *** search
/ Merciful 2 / Merciful - Disc 2.iso / software / b / blitzbasicv2.1b.dms / blitzbasicv2.1b.adf / libsdev.lha / DOCUMENTATION
Text File  |  1994-09-05  |  30KB  |  821 lines

  1.                    Blitz2 Library Developers Documents
  2.                              September 1994
  3.                       Mark Sibly and Simon Armstrong
  4.  
  5.  
  6.  
  7. INTRODUCTIONS
  8.  
  9. The following is a collection of articles, docs and so forth for those
  10. wanting to develop command libraries for Blitz2. Only those experienced
  11. in the ways of assembly programming will be interested.
  12.  
  13.  
  14. COPYRIGHT NOTICE
  15.  
  16. To help those wanting to develop libraries a large number of source codes
  17. have been included in this archive. All code include is copyright and
  18. hence should not be duplicated in other files without the author's
  19. express permission. Authors can be contacted via the address given in
  20. the documentation for each library published in BUM7.
  21.  
  22. Acid Software can be contacted either via email: at acid@iconz.co.nz or
  23. via fax on +649 358 1658.
  24.  
  25.  
  26. TOOLS OF THE TRADE
  27.  
  28. Before starting on your own libraries several programs and files will
  29. need to be setup in their correct position. First the blitzlibs: volume
  30. which includes the userlibs, amigalibs, basic and system directories
  31. should be installed on harddisk with an "ASSIGN BLITZLIBS: pathname"
  32. added to the your system's startup-sequence.
  33.  
  34. Along with the 4 directories in blitzlibs: (do NOT add any others)
  35. copy the res files included in this archive, in particular make
  36. sure the file blitzlibs:libmacs.res is able to be found by Blitz2.
  37.  
  38. You will also want to create executable versions of the libsdev tools,
  39. the src has been included in the toolssrc directory of this archive.
  40. It is probably easiest to compile them to your c: directory.
  41.  
  42.  
  43. OVERVIEW
  44.  
  45. Blitz2 has an expandable command set. When you startup Blitz2 it attempts
  46. to load the command set from the file Blitz2:DefLibs. If it cannot find
  47. this file it will load the command set from the Blitzlibs: directories.
  48.  
  49. Users are able to create new command libraries and add them to the
  50. userlibs directory of blitzlibs:. While developing a library remove
  51. the deflibs file from the Blitz2: drawer so that Blitz will always
  52. load it's commands from the BlitzLibs: volume. You can also override
  53. the DefLibs commands by select ReLoadLibs from the compiler menu.
  54.  
  55. After creating a new .obj file in your blitzlibs:userlibs drawer you
  56. can test your library select ReloadLibs and create a test program to
  57. use your new commands. If Blitz2 crashes with an "Out Of Memory" or
  58. some such error during loading of libs, you have obviously created
  59. an illegal library file and will have to remove it from Blitzlibs:userlibs
  60. before restarting Blitz2.
  61.  
  62. Other things to make sure of when creating library .obj files is to
  63. never have runtime errors enabled and never include any BASIC tokens
  64. (the END statement in particular), both these will create illegal
  65. library files.
  66.  
  67. Once your library is complete you can use the makedeflibs command to
  68. create a new Blitz2:DefLibs file so you can return to the fast loading
  69. Blitz2 you once new (Blitz2 is much quicker at loading DefLibs than
  70. scanning the entire BlitzLibs: volume).
  71.  
  72.  
  73. CONVERTING STANDARD AMIGA LIBRARIES...
  74.  
  75. If you just wish to access an unsupported standard amiga library (such
  76. as those that hang out in your libs: drawer) you will need to convert
  77. it's corresponding .fd file. You will notice the .fd file contains
  78. parameter and syntax information for all the commands in the .library
  79. file. By running the fdconvert tool, you can add a corresponding
  80. Blitz library in the BlitzLibs:AmigaLibs drawer which will let you
  81. access these commands from Blitz2. Make sure the .fd library specifies
  82. the name of the actual library in the top line (same as DOS3 standard
  83. .fd files).
  84.  
  85. The fdconvert program should assign a suitable library number for your
  86. new amigalib. Check the libnums.bb file in the ressrc file for
  87. what library number assigns have been made for amigalibs upto
  88. now (first available should be #217).
  89.  
  90. After running fdconvert either create a new deflibs file with the
  91. makedeflibs tools or use ReloadLibs in the Compiler menu of Blitz2.
  92. All the commands that were listed in the fd file should now be
  93. part of Blitz2, the only difference is that they are all succeeded
  94. by an underscore character to avoid clashes with Blitz2 tokens.
  95.  
  96.  
  97.  
  98. ---------------------------------------------------------------------------------
  99.       Text file taken from BUM7's readme directory by Simon Armstrong
  100. ---------------------------------------------------------------------------------
  101.  
  102.  
  103. Notes for Library Developers
  104.  
  105. Well, I've been a bit bamboozled by all the userlibs that have been
  106. arriving in the mail. The following are a few notes I've jotted down
  107. after spending a lot of time trying to tidy up what you guys have
  108. been sending in.
  109.  
  110. 1. LibNums and general naming conventions.
  111.  
  112. OK, first up, library numbers. Not a big deal as we are probably
  113. going to get rid of tokenising in Blitz3 so that 1. we don't get
  114. all the clashing that has been going on and 2. users can use what
  115. ever ascii editor they please. However in the mean time (and for
  116. ever more if the Amiga is still out of production by XMas)....
  117.  
  118. Do NOT use library numbers above 40. Especially do NOT go sticking
  119. your libraries in between Acid ones (ELMORE!!!) we left the odd
  120. numbers for our own expansion not yours! To be generous I have
  121. allocated the following for those that feature on BUM7 and are working
  122. on new libraries:
  123.  
  124. Elmore - 99 97 95, RI - 63 58 51, Neil - 50 49 48, Romulus- 47 46 45
  125.  
  126.  
  127. Secondly, do not use words like len, start and so forth (RI!!!). As
  128. BASIC programmers like to use such words for variables it is a bit
  129. rude to find that someone has gone and called a command after your
  130. favourite variable name (don't don't don't add a command called i!),
  131.  
  132. To be really snazzy you should try and use the library name (make it
  133. concise) in all your tokens like I have done in the display library,
  134. this makes things a lot easier to read, avoids token clashes (Elmore,
  135. any chance of a tokenclash tool?) and possibly keeps you on the straight
  136. and narrow.
  137.  
  138.  
  139. 2. Syntax and library content.
  140.  
  141. Avoid extraneous commands at all costs. If you can use different forms
  142. of the same command DOIT. If the command is the same as using two or
  143. three commands don't bother. Rule of thumb I suppose is add parameters
  144. to make key commands more powerful rather than adding more commands.
  145.  
  146. If you are just implementing small pieces of machine code to do miscellaneous
  147. jobs don't bother. Just stick the machine code in a statement and publish
  148. the statement. Commands added to Blitz2 should not be the sort that you
  149. can acheive in a few lines of code, they just make Blitz2 a more obese
  150. rather than ultra powerful language.
  151.  
  152. With the advent of the ASMEXIT command machinecode routines can now
  153. be placed in functions and statements in a stable manner. To use
  154. ASMEXIT do not use UNLK A4 but simply replace any RTS commands
  155. with ASMEXIT, ensure that registers a4-a6 are restored before
  156. ASMEXITting.
  157.  
  158. If you are adding commands that belong in Acid libraries, please ask me
  159. for the source for that particular library, and add them there, it makes
  160. my job a hell of a lot easier and means with new documentation users will
  161. know about your command cos they are looking in the correct section ot
  162. the manual.
  163.  
  164.  
  165. 3. A few other pointers...
  166.  
  167. * OS2/3 specific commands should check the version of exec and exit
  168.   cleanly if too old:
  169.  
  170.   MOVE.l 4,a0:CMP #36,20(a0):BCS doexit    ;wo older than v36!!!
  171.  
  172. * Use Blitz2 objects if they are suitable, best place to work out
  173.   how they work is in the source code the acidlibs I have included
  174.   in the libsdev archive. Hmmm, a quick lesson on this follows below.
  175.  
  176. * always use ALibJSR $c002 and $c003 for allocating and freeing
  177.   memory, never use the exec calls...
  178.  
  179.  
  180. 4. And please please please...
  181.  
  182. Prefix the name of you library with your handle or name, those finding
  183. to their horror the source of their libraries published here please
  184. update your own source codes with the changes I've made.
  185.  
  186. Keep a history file at the top of your library source, it makes keeping
  187. the documentation uptodate so much easier.
  188.  
  189. Test your commands with bad parameters to make sure your error checking
  190. is cool, save a .test file with your library when you submit it so others
  191. can see how to use your commands, and try and follow the documentation
  192. style that I've been using in BUM7. IE, list all the commands at the
  193. top then describe them one by one.
  194.  
  195. Keep your .res files in the root of blitzlibs:, reference all resident
  196. files in compiler options as blitzlibs:filename.res and use
  197. blitzlibs:userlibs as the path when creating object files. Getting a
  198. bit picky here I think. Oh DO take notice of the new keyboard shortcuts
  199. in the compiler menu.
  200.  
  201.  
  202. 5. And very importantly...
  203.  
  204. Make sure you return A4 how you found it, it is the local variable
  205. base and if you stuff it you will not be able to use your commands
  206. inside functions and procedures (yes I know I am guilty of this
  207. often).
  208.  
  209. Keep your library .obj files as small as possible. If you need a hunk
  210. of memory allocate it in the init routine, DON'T USE ds.l big. If you
  211. have a look up table try and generate it from allocated memory during
  212. initialisation rather than INCBIN the thing, DefLibs is too bloody
  213. big as it is, don't push it! Anything over 4K is no go unless it is
  214. major cool.
  215.  
  216. Use moveq whenever possible. It is fast and sign extends to a
  217. long word. Use pc relative adressing as much as possible as Blitz2
  218. does not optimise this. Use addq and subq also whenever possible.
  219.  
  220. Anyway, thanks for everyone who has been adding commands, please don't
  221. take the above personally just trying to keep things tidy...
  222.  
  223. Blitz2 Library Objects.
  224.  
  225.  
  226. Yes, bloody wonderful things. OK, say your library is based around a
  227. particular object or structure, hopefully something useful that will
  228. make Blitz2 programmers want to give you their girlfriends...
  229.  
  230. First up I define a NewType similar to the other Blitz2 objects as listed
  231. in an appendix of the Blitz2 manual, and define a macro to make my assembly
  232. code much more readable:
  233.  
  234. Macro s
  235.   {SizeOf.sound\`1}(a3)
  236. End Macro
  237.  
  238. NEWTYPE .sound
  239.   data.l
  240.   size.l
  241.   period.w
  242.   volume.w
  243.   priority.w
  244.   etc etc
  245. End NEWTYPE
  246.  
  247. Of course I call my library acidsoundlib so it doesn't get mixed up with
  248. everyone else's sound libraries, assign it a number (see above) and define
  249. the name of my sound object in the dumtoke, This allows the programmer to
  250. use the free object, addr object() etc. on my object.
  251.  
  252. #acidsoundlib=40                      ;library number at top as constant
  253.  
  254. !libheader {#acidsoundlib,init,1,0,0} ;header with init routine if needed
  255.  
  256. !dumtoke{"Sound","",_toke}            ;wo clash, only example ok?
  257.  
  258. !astatement
  259. !args {#word,#long,#word}
  260. !libs {#acidsoundlib,$1380}
  261. !subs {_initsound,0,0}
  262. !name {"InitSound","Sound#,length,flags"}
  263.  
  264. init:!nullsub {_initlib,0,0}
  265.  
  266. _load:!nullsub{0,0,0}
  267. _save:!nullsub{0,0,0}
  268. _use:!nullsub{0,0,0}
  269. _free:!nullsub{0,0,0}
  270.  
  271. !libfin{_toke,_load,_save,_use,_free,4,5}
  272.  
  273. OK, we don't worry about the nullsubs this week. the last two numbers in the
  274. libfin macro define the default number of objects (before the user increases
  275. them via the compiler options) and the size of the object which is 2^n so
  276. Blitz2 can do a shift to calculate the location of the object any parameter
  277. is referencing. The 5 means our object can take up to 32 bytes.
  278.  
  279. Hmmm, the !libs macro has the number $1380. There are some macros in libmacs for
  280. this but I always forget them. The high byte says which address register you
  281. want to point to the object, the low byte defines which parameter to use:
  282.  
  283. #a0=$1000:#a1=$1100:#a2=$1200:#a3=$1300:#a4=$1400:#a5=$1500:#a6=$1600
  284. #p0=$80:#p1=$81:#p2=$82:#p3=$83:#p4=$85:#p5=$85
  285.  
  286. So if I want the adress register a3 to point to the object# defined by the
  287. first parameter I use the code #a3+#p0 = $1380
  288.  
  289. If I had a copy sound command that needed source in a2 and destination in
  290. a3 I'd use the following setup:
  291.  
  292. !astatement
  293. !args {#word,#word}
  294. !libs {#acidsoundlib,$1280,#acidsoundlib,$1381}
  295. !subs {_copysound,0,0}
  296. !name {"CopySound","SrcSound#,DestSound#"}
  297.  
  298. And, gosh it's exciting... yes a2 and a3 will be preloaded all ready to go
  299. at the start of your routine. Use #word in !args for all parameters that
  300. refer to objects.
  301.  
  302. OK, thats about it, oh the macro and newtype stuff, basically if you always
  303. pass the object number in say a3 set up the macro as I have done and whenever
  304. you want to reference a field in the object you can use it's name e.g.
  305.  
  306. move.l !s{size},d1:move.l !s{data},d2
  307.  
  308. which is the same as
  309.  
  310. move.l 4(a3),d1:move.l 0(a3),d2
  311.  
  312. Hmmm, other things:
  313.  
  314.  
  315. 1. Objects are always initialised with zero's on program startup
  316.  
  317. 2. The free subroutine if you provide one will be called for all
  318.    objects on program exit.
  319.  
  320. 3. See banklib source for basic memory management.
  321.  
  322. 4. Use other libraries objects, but always check if they are initialised.
  323.  
  324.  
  325. ---------------------------------------------------------------------------------
  326.     Following republished from AmigaDownUnder article by Mark Sibly
  327. ---------------------------------------------------------------------------------
  328.  
  329.  
  330.                     HOW TO WRITE BLITZ BASIC 2 LIBRARIES
  331.                     ************************************
  332.  
  333.   The Blitz 2 compiler is heavily library orientated. What this means is
  334. that many of the routines and functions used by the compiler are not actually
  335. stored in the compiler itself, but in completely separate library files.
  336.  
  337.   This set up allows new commands and features to be easily added to the Blitz 2
  338. system, simply by creating a new library file.
  339.  
  340.   Libraries in Blitz 2 are usually written in Blitz 2 itself, and must be
  341. TOTALLY in machine code.
  342.  
  343.   Before we get into actually writing a library, let's first have a look at
  344. the basic layout of libraries in Blitz 2.
  345.  
  346.                         Varieties of Blitz 2 Libraries
  347.                         ******************************
  348.  
  349.   Blitz 2 makes use of 3 types of libraries - system libraries, Amiga libraries
  350. and command libraries. Let's have a closer look at these:
  351.  
  352. * System libraries - These libraries are used internally by the Blitz 2
  353.   compiler and include such mundane operations as memory allocation, string
  354.   manipulation and so on. System libraries will only ever be modified by Acid
  355.   software, as they work in connection with Blitz 2 at a very low level.
  356.  
  357. * Amiga libraries - These libraries allow Blitz 2 programmers access to any
  358.   of the operating system libraries (eg: intuition.library,exec.library).
  359.  
  360. * Command libraries - These libraries form the bulk of the Blitz 2 system, as
  361.   they contain all the BASIC commands and functions available to Blitz 2
  362.   programmers. All of the Window, Screen, Blitting etc. commands are held in
  363.   command libraries. To add new commands to Blitz 2, a command library should
  364.   be created containing these new commands, and this is just what we'll be
  365.   doing...soon...
  366.  
  367.                   Where ARE the Blitz 2 Libraries to be found?
  368.                   ********************************************
  369.  
  370.   When Blitz 2 starts up, it needs to be able to locate all the libraries
  371. available. It does this by first looking for a file called 'Blitz2:Deflibs'
  372. (for 'default libraries'). If this file is not found, Blitz 2 then goes and
  373. looks for a directory called 'Blitzlibs:'. If neither Deflibs or Blitzlibs:
  374. can be found, then Blitz 2 gives up and politely (?) exits.
  375.  
  376.   If Blitz 2 can find Deflibs, then it uses the contents of Deflibs as it's
  377. libraries. If Blitz 2 can only find Blitzlibs:, it then proceeds to scan any
  378. sub-directories of Blitzlibs:, and uses any files found as it's libraries.
  379. At the moment, there are 4 sub-directories set up within blitzlibs: - 'System',
  380. 'Amigalibs', 'Basic' and 'Userlibs'.
  381.  
  382.   It's worth pointing out here that Deflibs is simply all the separate Blitzlibs:
  383. libraries joined together as one continuous file. This was done to speed up
  384. the library loading process, and to make the whole system more user-friendly.
  385. A program called 'Makedeflibs' can be used to create the Deflibs file from
  386. the individual Blitzlibs: libraries.
  387.  
  388.                               Getting started
  389.                               ***************
  390.  
  391.   First, you'll need to unarchive the 'blitzlibs.lha' file into a blitzlibs
  392. directory, and add yet another assign to your startup-sequence (eg: assign
  393. blitzlibs: blitzlibs). Next, get rid of 'Blitz2:deflibs' to prevent Blitz 2
  394. from looking for it instead of blitzlibs:. This can be done simply by moving
  395. Deflibs from the Blitz2: directory to a different directory, or by renaming
  396. it.
  397.  
  398.   Next, crank up Blitz 2 to make sure everything's still going OK. You should
  399. notice Blitz 2 takes longer to startup, due to it having to load in the
  400. individual library files from blitzlibs:.
  401.  
  402.                          Writing a Blitz 2 Library
  403.                          *************************
  404.  
  405.   Before you can go ahead with writing your library, you'll have to first
  406. choose a 'number' for your library. Each library in Blitz 2 has it's own unique
  407. identifying number, so you must make sure the number you choose for your library
  408. does not clash with any other libraries.
  409.  
  410.   Acid software has decided, in it's infinite wisdom, that any libraries under
  411. development should be given a library number from 10...50. So, you'll probably
  412. choose 10 for your first library, 11 for your second, and so on...
  413.  
  414.   If you finish a library and are pretty proud of it and feel it would be of
  415. benefit to Blitz users in general, Acid software can be contacted to obtain
  416. a permanent library number.
  417.  
  418.   One more thing you'll need to write your library is the 'libmacs.res'
  419. resident file. This file contains a set of macros and constants necessary
  420. for writing libraries. If you're not familiar with resident files, refer to
  421. the Blitz 2 User guide section 10-1.
  422.  
  423.   Libmacs.res can be found in the Blitzlibs: directory, and before starting
  424. work on a library you'll need to load it in via the 'Compiler/Options'
  425. menu.
  426.  
  427.   OK, so you've got libmacs.res loaded and you've decided upon your library
  428. number. It's now time to get coding!...
  429.  
  430.   We'll start of with a quick example library that doesn't do all that much
  431. but should give you an idea of what's going on:
  432.  
  433.  
  434. ;
  435. ;examplelib
  436. ;
  437. ;An example of library writing in Blitz 2
  438. ;
  439. ;A decidedly useless command to blink your LED on/off
  440. ;
  441. ;we're going to give our library the number 10...
  442.  
  443. #mylib=10
  444.  
  445. ;***** First up, a header for the library... *****
  446.  
  447. !libheader{#mylib,0,0,0,0}
  448.  
  449. ;***** now, the actual commands in the library *****
  450.  
  451. !astatement
  452. !args{#word}
  453. !libs{#graphicslib,#la6}
  454. !subs{doblink,0,0}
  455. !name{"Blink","number of blinks"}
  456.  
  457. ;That's it!
  458.  
  459. !libfin
  460.  
  461. ;***** Now comes the code for the library *****
  462.  
  463. doblink
  464. ;
  465. MOVE d0,d2:BEQ 'skip:SUBQ #1,d2
  466. 'loop
  467. BCHG #1,$bfe001:JSR -270(a6)    ;call graphics library 'Wait top of frame'
  468. DBF d2,'loop
  469. 'skip:RTS
  470.  
  471. ;***** That's all for our library! *****
  472.  
  473.  
  474.   Once you've typed this in, save it, then create an executable by the name of
  475. 'Blitzlibs:userlibs/examplelib.obj'.
  476.  
  477.   To test out your library, use the 'Compiler/Reload Libs' menu item. This
  478. will force Blitz 2 to re-load all it's libraries from Blitzlibs:. Following
  479. this, your awesomely useful 'Blink' command should now be available to
  480. Blitz 2...
  481.  
  482. ;
  483. ;Test of the new 'Blink' command...
  484. ;
  485. Blink 10    ;blink ten frames....
  486. ;
  487.  
  488.   Now, let's go through the examplelib a line at a time:
  489.  
  490. !libheader{#mylib,0,0,0,0}
  491.  
  492.   The !libheader macro should always appear at the start of a library.
  493. The libheader macro looks like this:
  494.  
  495. !libheader{library number,initialize,return,cleanup,runerrs}
  496.  
  497.   The 'initialize' parameter allows you to specify a routine which gets
  498. executed when a Blitz 2 program is run. Likewise, 'finish' may specify
  499. a clean up routine when the program ends. If either of these is set to 0,
  500. then they are ignored.
  501.  
  502.   The 'return' parameter allows the library's initialise routine to return
  503. a value, in d0, which other libraries may access. If this parameter is 0,
  504. then this means the libraries initialization returns nothing. If this parameter
  505. is 1, this means the initialization routine returns a value in d0 which other
  506. libraries may access. We'll have a closer look at this when we get to the
  507. !libs bit...
  508.  
  509.   'Cleanup' is similar to 'initialize', allowing the library to doing any
  510. tidying up when the program ends.
  511.  
  512.   The 'runerrs' parameter informs Blitz2 of where any runtime error checking
  513. code is located. We'll go into this later as well.
  514.  
  515.   After the libheader, the library then goes on to specify the actual commands
  516. in the library - in this case, there is only one command...
  517.  
  518. !astatement
  519. !args{#word}
  520. !libs{#graphicslib,#la6}
  521. !subs{doblink,0,0}
  522. !name{"Blink","number of blinks"}
  523.  
  524.   The !astatement macro specifies that this command is a statement, as
  525. opposed to a function. In other words, Blink doesn't return any value.
  526.  
  527.   The !args macro gives the arguement template for our command. In this case,
  528. !args{#word} means that the Blink command takes only 1 parameter - a 16 bit
  529. word. We can specify as many parameters as we want here, and they may be any
  530. of the following types:
  531.  
  532. #byte
  533. #word
  534. #long
  535. #quick
  536. #float
  537. #string
  538.  
  539.   Parameters are passed to library routines through the 68000 data registers
  540. D0 through D6 - the first parameter being passed in d0, the second in D1 and so
  541. on. If there are more than 7 parameters, extra parameters get passed on the
  542. stack. Also, string variables are passed through the use of a data register
  543. as a pointer to the string, and the length of the string on the stack. We'll
  544. cover stack usage in more detail a bit later on.
  545.  
  546.   Onto the !libs macro. This macro allows us to 'grab' data from other
  547. Blitz 2 libraries for use by our command...
  548.  
  549. !libs{#graphicslib,#la6}
  550.  
  551.   In this case, we are asking for the 'graphics.library' library base to be
  552. placed in A6 before our blink routine is called. Remember the 'initialise'
  553. and 'return' parameters of the !libheader macro? Well, the Blitz 2 library
  554. 'graphicslib' uses these parameters to open the graphics library and return
  555. the library base in d0 for other libraries to use.
  556.  
  557.   We can also specify multiple libraries using the !libs macro. For example:
  558.  
  559. !libs{#graphicslib,#la6,#intuitionlib,#ld6}
  560.  
  561.   Will give us graphics base in a6, and intuition base in d6.
  562.  
  563.   Now we get to the !subs macro:
  564.  
  565. !subs{doblink,0,0}
  566.  
  567.   This simply contains a pointer to the actual code to execute once all
  568. parameters and library values have been placed in appropriate registers.
  569.  
  570.   The 2 '0' parameters here are used for runtime error checking purposes.
  571. More on this later.
  572.  
  573.   Finally, we get to name our new command:
  574.  
  575. !name{"Blink","number of blinks"}
  576.  
  577.   The !name macro takes at least 2 text parameters. The first gives the
  578. actual name of the command, while the second specifies the 'help' text for
  579. the command. A third parameter may be given allowing a label to be associated
  580. with the text - this is of use when creating Blitz 2 objects (see below).
  581.  
  582.   Once we've finished specifying the format of our libraries commands, we
  583. use the !libfin macro:
  584.  
  585. !libfin
  586.  
  587.   The rest of the program contains the actual machine code to perform the
  588. Blink command.
  589.  
  590.                                   FUNCTIONS
  591.                                   *********
  592.  
  593.   Blitz 2 functions are created almost identically to statements, except we use
  594. the !afunction macro instead of !astatement. The !afunction macro must
  595. be supplied with a single parameter indicating what type of result is returned
  596. by the function. Then, it's up to the actual function code to return the
  597. appropriate type of value in D0.
  598.   Let's expand our library to demonstrate writing a function...
  599.  
  600.  
  601. ;
  602. ;examplelib
  603. ;
  604. ;An example of library writing in Blitz 2
  605. ;
  606. ;A decidedly useless command to blink your LED on/off
  607. ;
  608. ;we're going to give our library the number 10...
  609.  
  610. #mylib=10
  611.  
  612. ;***** First up, a header for the library... *****
  613.  
  614. !libheader{#mylib,0,0,0,0}
  615.  
  616. ;***** now, the actual commands in the library *****
  617.  
  618. !astatement
  619. !args{#word}
  620. !libs{#graphicslib,#la6}
  621. !subs{doblink,0,0}
  622. !name{"Blink","number of blinks"}
  623.  
  624. !afunction{#word}               ;inidcates that this function returns a word.
  625. !args
  626. !libs
  627. !subs{doledstatus,0,0}
  628. !name{"LEDStatus",""}
  629.  
  630. ;That's it!
  631.  
  632. !libfin
  633.  
  634. ;***** Now comes the code for the library *****
  635.  
  636. doblink
  637. ;
  638. MOVE d0,d2:BEQ 'skip:SUBQ #1,d2
  639. 'loop
  640. BCHG #1,$bfe001:JSR -270(a6)    ;call graphics library 'Wait top of frame'
  641. DBF d2,'loop
  642. 'skip:RTS
  643.  
  644. doledstatus
  645. ;
  646. BTST #1,$bfe001:SNE d0:EXT d0:RTS
  647.  
  648. ;***** That's all for our library! *****
  649.  
  650.  
  651.                    LIBRARY INITIALIZATION AND CLEAN UP
  652.                    ***********************************
  653.  
  654.   If your library needs to perform some kind of initialization or cleaning up,
  655. the 'initialize' or 'cleanup' parameters of the !libheader macro may be used.
  656. However, instead of simply pointing to some code, these parameters should
  657. point to a !nullsub macro. A WHAT!?!? Well, !nullsub is basically a combination
  658. of the !subs and !libs macros. The first 3 parameters of !nullsub are the same
  659. as those for !subs, while the rest allow you to pickup values from other
  660. libraries similar to the !libs macro. This set up allows you import data from
  661. an external library for use during initialization or cleanup. For example,
  662. let's say you need intuition base to perform your libraries initialization and
  663. cleaning up:
  664.  
  665. !libheader{#mylib,init,0,cleanup,0}
  666.  
  667. init
  668. !nullsub{doinit,0,0,#intuitionlib,#la6}
  669.  
  670. cleanup
  671. !nullsub{docleanup,0,0,#intuitionlib,#la6}
  672.  
  673. .
  674. .
  675. .
  676.  
  677. !libfin
  678.  
  679. doinit      ;actual initialization code...
  680.  
  681. docleanup   ;clean up code...
  682.  
  683.   Note that libraries are initialized numerically, from higher numbered
  684. libraries to lower numbered. Therefore, if you have written 2 libraries of
  685. which one requires the returned value from the other, the library supplying
  686. the value should be of a higher library number than the one receiving.
  687.   Also note that the !nullsub macro should appear between the !libheader
  688. and !libfin macros - NOT in the main code.
  689.  
  690.                                 THE STACK
  691.                                 *********
  692.  
  693.   Parameters are normally passed to library routines through data registers
  694. D0 through D6. However, in the case of string variables, or when a command
  695. requires more than 7 parameters, parameters may end up on the stack. To help
  696. in keeping track of stacked parameters, Blitz 2 copies the stack pointer to
  697. address register A2 before anything gets placed on the stack. This allows
  698. you to step through stacked parameters using the -(A2) addressing mode instead
  699. of having to play around with offsets from A7. For example, say you're writing
  700. a command which requires one string parameter. When the commands routine is
  701. called, the address of the string will be in D0, and the strings length will be
  702. on the stack. The routine could then pick up the strings length using:
  703.  
  704. move.l -(a2),d1
  705.  
  706.   Note that Blitz 2 Version 1.80 and higher will automatically null terminate
  707. all strings. Earlier versions only null terminate the last string of a
  708. parameter list.
  709.   Also remember that if you're wanting to use A2 in this way, you must not
  710. use A2 in the !libs macro.
  711.  
  712.  
  713.                           RUNTIME ERROR CHECKING
  714.                           **********************
  715.  
  716.   Blitz 2 libraries may also contain runtime error checking code. This code may
  717. be used to check that command (or function) parameters are within a legal range.
  718. Remember, this extra code will only be executed if the 'RUNTIME ERROR CHECKING'
  719. option within the compiler/options menu is enabled.
  720.   Error checking code must always appear at the end of a library. This
  721. allows Blitz 2 to drop this code when runtime error checking is disabled.
  722.   To add error checking to a library, you need to indicate where in the
  723. library the actual error checking code starts. This is done through the
  724. 'runerrs' parameter of the '!libheader' macro. Then, it's simply a case of
  725. using the '!subs' macro to indicate any error checking routines that needs to be
  726. called.
  727.   If an error checking routine decides that a parameter is bad, a 'TRAP #0'
  728. should be executed with D0 pointing to an appropriate error message string.
  729.   To demonstrate this, we'll alter our example library to make sure 'Blink' only
  730. allows parameters of 0...100:
  731.  
  732. ;
  733. ;examplelib
  734. ;
  735. ;An example of library writing in Blitz 2
  736. ;
  737. ;A decidedly useless command to blink your LED on/off
  738. ;
  739. ;we're going to give our library the number 10...
  740.  
  741. #mylib=10
  742.  
  743. ;***** First up, a header for the library... *****
  744.  
  745. !libheader{#mylib,0,0,0,runerrs}
  746.  
  747. ;***** now, the actual commands in the library *****
  748.  
  749. !astatement
  750. !args{#word}
  751. !libs{#graphicslib,#la6}
  752. !subs{doblink,doblinkcheck,0}
  753. !name{"Blink","number of blinks"}
  754.  
  755. !afunction{#word}               ;inidcates that this function returns a word.
  756. !args
  757. !libs
  758. !subs{doledstatus,0,0}
  759. !name{"LEDStatus",""}
  760.  
  761. ;That's it!
  762.  
  763. !libfin
  764.  
  765. ;***** Now comes the code for the library *****
  766.  
  767. doblink
  768. ;
  769. MOVE d0,d2:BEQ 'skip:SUBQ #1,d2
  770. 'loop
  771. BCHG #1,$bfe001:JSR -270(a6)    ;call graphics library 'Wait top of frame'
  772. DBF d2,'loop
  773. 'skip:RTS
  774.  
  775. doledstatus
  776. ;
  777. BTST #1,$bfe001:SNE d0:EXT d0:RTS
  778.  
  779. ;***** OK, time for runtime error checking code! *****
  780.  
  781. runerrs
  782.  
  783. blinkcheck
  784. CMP #101,d0:BCC blinkerror:RTS
  785.  
  786. blinkerror:MOVE.l #blinkerrortext,d0:TRAP #0
  787.  
  788. blinkerrortext:DC.b "Number of blinks must be 0...100",0:EVEN
  789.  
  790. ;***** That's all for our library! *****
  791. ;
  792.  
  793.                       WARNING! WARNING! WARNING!
  794.                       **************************
  795.  
  796.   Any library routines, whether they be statements, functions, runtime error
  797. checks or simply initialization code, MUST preserve address registers A4, A5
  798. and A6. As well, a function MUST ALSO preserve address register A3. Just what
  799. are these registers used for?
  800.  
  801. A6 : Blitz keeps track of A6 to prevent it having to be unnecessarily
  802.      re-loaded.
  803. A5 : Blitz 2's global variable base.
  804. A4 : Blitz 2's local variable base.
  805. A3 : Blitz uses this to build temporary strings.
  806.  
  807.  
  808.                           THAT'S ALL FOLKS
  809.                           ****************
  810.  
  811.   Hopefully, you'll now have enough information to begin writing your own
  812. libraries. In the next installment of this series, we'll have a closer look
  813. at string variables in Blitz 2, creating Blitz 2 objects and more. In the
  814. interests of keeping this document as self contained as possible, I'll finish
  815. up with the source code to libmacs...
  816.  
  817. Plesant programming,
  818.  
  819. Mark Sibly
  820.  
  821.